package logo

import (
	"fmt"
	"os"
	"regexp"
	"strings"
)

const (
	needHandleContextNum = 25553
)

var (
	bar = NewBarOption(0, needHandleContextNum)
)

var (
	targetLogo        string
	matchFileCount    int
	matchContentCount int
)

var (
	regGs = regexp.MustCompile(`[^a-zA-Z]gs_|^gs_`)
)

type ReplaceFunc func(path, old, target string)

type dirTreeNode struct {
	name     string
	fullName string
	prefix   string
	child    []*dirTreeNode
	IsDir    bool
}

// Print show file tree
func (d *dirTreeNode) Print(space int) {
	fmt.Println(strings.Repeat(" ", space), "├── ", d.name)
	if d.child != nil {
		space += 4
		for _, i := range d.child {
			i.Print(space)
		}
	}
}
func (d *dirTreeNode) getFullName() string {
	return d.prefix + "/" + d.name
}

// ReplaceGsName  replace gs_ to iss_
func (d *dirTreeNode) ReplaceGsName(reg *regexp.Regexp) {
	if d.IsDir {
		for _, i := range d.child {
			i.ReplaceGsName(reg)
		}
	}
	d.name = replaceName(d.prefix, d.name, reg, oldLog, targetLogo)
	d.name = replaceName(d.prefix, d.name, regexp.MustCompile(`openGauss`), openGauss, isseDB)
	d.name = replaceName(d.prefix, d.name, regexp.MustCompile(`opengauss`), opengauss, issedb)
	if d.IsDir {
		return
	}
	err := replaceContent(d.getFullName())

	if err != nil {
		fmt.Println(d.name, " ", d.prefix, " ", d.IsDir)
		panic(err)
	}

}

// PrintLine if match reg, print the line
// the table header is : [file,   line,  content]
func (d *dirTreeNode) PrintLine(reg *regexp.Regexp) {

}

func ChangeGsFile(dir, targetGs string) {
	dir, _ = strings.CutSuffix(dir, "/")
	node, err := GetDir(dir)
	if err != nil {
		panic(err)
	}

	targetLogo = targetGs

	node.ReplaceGsName(regGs)
	bar.Finish()

	fmt.Println("\nmodify total file and directory: ", matchFileCount)
	fmt.Println("replace is_      : ", matchContentCount)
	fmt.Println("replace openGauss: ", openGaussNum)
	fmt.Println("replace opengauss: ", opengaussNum)

	if matchContentCount != 24976 && strings.Contains(dir, "openGauss-server") {
		errMsg := fmt.Errorf("v5.0.0 need modify context total: %d", 24976)
		fmt.Println(errMsg)
	}
	fmt.Println("cd isseDB-server && sh build.sh -3rd /root/binarylibs")
}

func GetDir(pathName string) (*dirTreeNode, error) {
	rd, err := os.ReadDir(pathName)
	if err != nil {
		return nil, fmt.Errorf("open file ./openGauss-server failed")
	}
	var tree, childNode *dirTreeNode
	tree = &dirTreeNode{
		fullName: pathName,
		IsDir:    true,
	}

	tree.fullName = pathName
	tree.prefix, tree.name = split(pathName)
	for _, fileDir := range rd {
		name := fileDir.Name()
		// 只修改gs_ 开头的文件，忽略 .git
		if name == ".git" || name == ".gitee" {
			continue
		}
		fullName := pathName + "/" + name
		if fileDir.IsDir() {
			childNode, err = GetDir(fullName)
			if err != nil {
				panic(err)
			}
		} else {
			childNode = &dirTreeNode{
				prefix: pathName,
				name:   name,
				IsDir:  false,
				child:  nil,
			}
		}
		tree.child = append(tree.child, childNode)
	}
	return tree, nil
}

func replaceName(pathName, name string, reg *regexp.Regexp, old, target string) string {
	// [^] # 匹配一个不在指定范围内的字符，如：/[^a-zA-Z]gs_/匹配不包含a-z和A-Z的一个字母开头,紧跟gs_的行。
	if reg == nil {
		return name
	}
	if !reg.Match([]byte(name)) {
		return name
	}
	newName := pathName + "/" + strings.Replace(name, old, target, -1)
	fullName := pathName + "/" + name
	err := os.Rename(fullName, newName)
	if err != nil {
		fmt.Println("change failed: ", err.Error())
		return name
	}
	matchFileCount++
	return strings.Replace(name, old, target, -1)
}

func split(path string) (prefix, name string) {
	if len(path) == 0 {
		panic("please input valid path")
	}

	if path == "." {
		return ".", ""
	}

	pathArray := strings.Split(path, "/")
	l := len(pathArray)
	max := l - 1
	if l == 0 {
		return "", path
	}
	return strings.Join(pathArray[:max], "/"), pathArray[max]
}
